[FEATURE] Add public API to set / get vertex positions of visual rigid geometries.#2776
Merged
duburcqa merged 8 commits intoMay 13, 2026
Merged
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0c6587a54c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
801530e to
263f344
Compare
…ero-copy fallback kernel
Allocating vverts_state.pos at (n_vverts, B) for every kinematic entity scales linearly with mesh size and env count, which is unacceptable for scenes with large kinematic meshes. Introduce a per-entity opt-in flag (custom_vverts on Mesh / Primitive / URDF / MJCF / USD via CustomVvertsMixin) and resize vverts_state / vverts_info / vfaces_info to n_custom_vverts_ / n_custom_vfaces_ - only entities that explicitly opt in get persistent storage. set_vverts / get_vverts now raise on non-opted entities. Also fix a non-contiguous tensor crash in the kernel fallback path by calling .contiguous() on the broadcast_tensor result.
3436e7e to
90d2422
Compare
The migration-forward branch in update_rigid queued an update_buffer call against get_buffer_id(node, "pos") for a freshly-added pyrender node, but pyrender allocates the GL buffers lazily during the upcoming render pass. The buffer id resolves to -1 at queue time, so the first frame after a set_vverts-triggered migration was silently dropped and rendered the initial sphere positions. Seed primitive.positions on the new node so the first GL upload uses the current vverts_state directly. Add tests/test_render.py::test_set_vverts_sphere_to_box covering the morph: a grid- subdivided cube (602 verts, vertices at every cube corner) is spherified for the deformable's initial mesh; top-down segmentation masks of the deformable before, after set_vverts(cube_verts), and after set_vverts(None) are compared against gs.morphs.Sphere and gs.morphs.Box references. Box comparison is byte-equal (corner vertex alignment), sphere comparison allows 0.5% boundary-pixel jitter (different tessellations).
|
🔴 Benchmark Regression Detected ➡️ Report |
90d2422 to
459803c
Compare
459803c to
f231ada
Compare
|
🔴 Benchmark Regression Detected ➡️ Report |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
vverts_statetoKinematicSolveras the single engine-side ground truth for per-frame world-space visual vertex positions. Surfacesset_vverts/get_vvertsat solver, entity, and vgeom levels. Rasterizer picks up user overrides via a lazy migration to per-env vertex-buffer rendering; collision/sdf rendering is unchanged.This is the renderer half. PR #2769 (visual-mesh raycasting) rebases on top of this — its
kernel_copy_custom_vvertsand parallel_custom_vvertsbuffer go away becausevverts_stateis now the engine-level buffer everyone reads.Supersedes the closed #2768 by relocating the buffer from
KinematicEntityto the solver.Design
vverts_state.pos: gs.qd_vec3, (n_vverts_, B)— populated bykernel_update_all_vverts(vgeom-pose ×init_pos) inKinematicSolver.update_vgeoms.vverts_info.is_custom: gs.qd_int— flips to 1 for entries written byset_vverts. FK skips them so user data survivesstep().KinematicOptions.batch_vverts_info: bool = False(mirrorsbatch_links_info/batch_dofs_info/batch_joints_info). When True, the wholevverts_infostruct gains aBdimension; without it, partialenvs_idxonset_vvertsraises.set_vverts(verts, envs_idx=None)/get_vverts(envs_idx=None)atKinematicSolver,KinematicEntity,Vgeom.vverts=Noneclears. Plane entities are refused.vverts_state.poseach frame. Clear migrates back; the restored render is byte-identical to baseline.set_vvertswhen supported; warns once per build on non-zero-copy backends and uses a fallback kernel.Test plan
tests/test_render.py::test_set_vverts[False-RASTERIZER]and[True-RASTERIZER]cover the API + render path end-to-end (round-trip, broadcast forms, get-returns-copy, vgeom-level write, Plane refusal, migration back, partial-envs error for unbatched, mixed user/FK envs for batched).vverts_infobatching change doesn't break existing consumers (only one ingenesis/vis/batch_renderer.py; adjusted to take env-0 slice when batched).Relationship to other PRs
_custom_vvertsbuffer is gone; engine state on the solver is the new ground truth.kernel_copy_custom_vverts(obsolete —vverts_stateis already the ground truth)._update_visual_bvh_for_solver(just callsolver.update_vgeoms(); FK is properly wired now).entity.has_custom_vvertschecks withis_custom-based logic where still needed.